﻿#pragma once
#include <string>
#pragma comment (lib,"OpenCL.lib")

#pragma region 测试

extern "C" __declspec(dllexport)
void Add(int a, int b, int* x)
{
	*x = a + b;
}

#pragma endregion

int convertToStringEx(const char* filename, std::string& s);

#pragma region 平台与设备

int GetPlatformInfoX(cl_platform_id pid, char* name, int* len, cl_platform_info info)
{
	size_t ret;
	cl_int CL_err = CL_SUCCESS;
	cl_platform_id id = pid;
	if (name == NULL)
	{
		CL_err = clGetPlatformInfo(id, info, 0, NULL, &ret);
	}
	else
	{
		CL_err = clGetPlatformInfo(id, info, *len, name, &ret);
	}
	*len = (int)ret;
	if (CL_err == CL_SUCCESS)
		return 0;
	else
		return CL_err;
};

extern "C" __declspec(dllexport)
int GetPlatforms(void* ptr, int* count);

//Opencl平台名称
extern "C" __declspec(dllexport)
int GetPlatformName(cl_platform_id platformid, char* name, int* length)
{
	return GetPlatformInfoX(platformid, name, length, CL_PLATFORM_NAME);
};

//平台支持的最大Opencl版本
extern "C" __declspec(dllexport)
int GetPlatformVersion(cl_platform_id platformid, char* name, int* length)
{
	return GetPlatformInfoX(platformid, name, length, CL_PLATFORM_VERSION);
};

//获取平台开发商名称
extern "C" __declspec(dllexport)
int GetPlatformVendor(cl_platform_id platformid, char* name, int* length)
{
	return GetPlatformInfoX(platformid, name, length, CL_PLATFORM_VENDOR);
};

//获取OpenCL平台支持的扩展名列表
extern "C" __declspec(dllexport)
int GetPlatformExtensions(cl_platform_id platformid, char* name, int* length)
{
	return GetPlatformInfoX(platformid, name, length, CL_PLATFORM_EXTENSIONS);
};

/*
获取OpenCL平台支持的功能类型
FULL_PROFILE:支持OpenCL规范的所有功能
EMBEDDED_PROFILE：支持OpenCL嵌入式简档，即OpenCL规范的一个子集
*/
extern "C" __declspec(dllexport)
int GetPlatformProfile(cl_platform_id platformid, char* name, int* length)
{
	return GetPlatformInfoX(platformid, name, length, CL_PLATFORM_PROFILE);
};

/*
设备类型：
CL_DEVICE_TYPE_DEFAULT    ：系统中的默认OpenCL设备，但不能是CL_DEVICE_TYPE_CUSTOM类型
CL_DEVICE_TYPE_CPU        ：CPU作为OpenCL设备
CL_DEVICE_TYPE_GPU        ：GPU作为OpenCL设备
CL_DEVICE_TYPE_ACCELERATOR：计算加速器作为OpenCL设备
CL_DEVICE_TYPE_CUSTOM     ：不支持OpenCL C编程的设备
CL_DEVICE_TYPE_ALL        ：除CL_DEVICE_TYPE_CUSTOM外的所有OpenCL设备
*/
extern "C" __declspec(dllexport)
int GetDevices(cl_platform_id pid, void* ptr, int* num)
{
	cl_uint numd;
	cl_int CL_err = CL_SUCCESS;
	if (ptr == NULL)
	{
		CL_err = clGetDeviceIDs(pid, CL_DEVICE_TYPE_ALL, 0, NULL, &numd);
	}
	else
	{
		CL_err = clGetDeviceIDs(pid, CL_DEVICE_TYPE_ALL, *num, (cl_device_id*)ptr, &numd);
	}
	*num = numd;
	if (CL_err == CL_SUCCESS)
		return 0;
	else
		return CL_err;
};

/// <summary>
/// 查询不同的属性信息对应的返回值类型不同，若接收返回值的变量类型与所需类型不一致，可能造成查询属性信息输出结果不正确
/// </summary>
/// <param name="id"></param>
/// <param name="ptr"></param>
/// <param name="len"></param>
/// <param name="info"></param>
/// <returns></returns>
int GetDeviceInfoX(cl_device_id id, void* ptr, int* len, cl_device_info info)
{
	size_t ret;
	cl_int CL_err = CL_SUCCESS;
	if (ptr == NULL)
	{
		CL_err = clGetDeviceInfo(id, info, 0, NULL, &ret);
	}
	else
	{
		CL_err = clGetDeviceInfo(id, info, *len, ptr, &ret);
	}
	*len = (int)ret;
	if (CL_err == CL_SUCCESS)
		return 0;
	else
		return CL_err;
};

extern "C" __declspec(dllexport)
int GetDeviceName(cl_device_id deviceid, char* name, int* length)
{
	return GetDeviceInfoX(deviceid, name, length, CL_DEVICE_NAME);
};

extern "C" __declspec(dllexport)
int GetDeviceVersion(cl_device_id deviceid, char* version, int* length)
{
	return GetDeviceInfoX(deviceid, version, length, CL_DEVICE_VERSION);
};

extern "C" __declspec(dllexport)
int GetDeviceExtensions(cl_device_id deviceid, char* exts, int* length)
{
	return GetDeviceInfoX(deviceid, exts, length, CL_DEVICE_EXTENSIONS);
};

extern "C" __declspec(dllexport)
int GetDeviceMaxComputeUnits(cl_device_id deviceid, uint32_t * count, int* length)
{
	return GetDeviceInfoX(deviceid, count, length, CL_DEVICE_MAX_COMPUTE_UNITS);
};

extern "C" __declspec(dllexport)
int GetDeviceMaxWorkItemDimensions(cl_device_id deviceid, uint32_t * count, int* length)
{
	return GetDeviceInfoX(deviceid, count, length, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS);
};

extern "C" __declspec(dllexport)
int GetDeviceMaxWorkGroupSize(cl_device_id deviceid, uint32_t * count, int* length)
{
	return GetDeviceInfoX(deviceid, count, length, CL_DEVICE_MAX_WORK_GROUP_SIZE);
};

extern "C" __declspec(dllexport)
int GetDeviceMaxWorkItemSizes(cl_device_id deviceid, uint32_t * count, int* length)
{
	return GetDeviceInfoX(deviceid, count, length, CL_DEVICE_MAX_WORK_ITEM_SIZES);
};

extern "C" __declspec(dllexport)
int SupportExtensions(cl_device_id deviceid, char* ext)
{
	size_t len;
	cl_int ret = 0;
	ret = clGetDeviceInfo(deviceid, CL_DEVICE_EXTENSIONS, 0, NULL, &len);
	if (ret != CL_SUCCESS)
	{
		return -abs(ret);
	}
	int r = 0;
	char* exts = (char*)malloc(sizeof(char) * len);
	ret = clGetDeviceInfo(deviceid, CL_DEVICE_EXTENSIONS, len, exts, &len);
	if (ret != CL_SUCCESS)
	{
		r = -abs(ret);
	}
	else
	{
		if (strstr(exts, ext))
		{
			r = 1;
		}
		else
			r = 0;
	}
	free(exts);
	return r;
};

extern "C" __declspec(dllexport)
int GetDevicePECount(cl_device_id deviceid, long* pe)
{
	size_t len;
	cl_context context = clCreateContext(NULL, 1, &deviceid, NULL, NULL, NULL);
	//创建程序对象
	char srcc[] = "__kernel void test(){}";
	const char* src = srcc;
	size_t sourceSize[] = { strlen(srcc) };
	cl_program program = clCreateProgramWithSource(
		context,
		1,
		&src,
		sourceSize,
		NULL);
	//编译程序对象
	cl_int status = clBuildProgram(program, 1, &deviceid, NULL, NULL, NULL);
	cl_int ret;
	cl_kernel kernel = clCreateKernel(program, "test", &ret);
	status = clGetKernelWorkGroupInfo(kernel, deviceid, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, 8, pe, &len);

	clReleaseContext(context);
	clReleaseProgram(program);
	clReleaseKernel(kernel);

	return ret;
}

#pragma endregion

#pragma region 上下文

extern "C" __declspec(dllexport)
int CreateContext(uint64_t did, cl_context * ptr)
{
	cl_device_id _did = (cl_device_id)did;
	cl_context context = clCreateContext(NULL,
		1,
		&_did,
		NULL, NULL, NULL);
	*ptr = context;
	return 0;
}

#pragma endregion

#pragma region 命令队列

extern "C" __declspec(dllexport)
int CreateCommandQueue(uint64_t did, cl_context * ctx, cl_command_queue * ptr)
{
	cl_context context = *ctx;
	cl_device_id device = (cl_device_id)did;
	cl_int ret;
	cl_command_queue commandQueue = clCreateCommandQueueWithProperties(context, device, NULL, &ret);
	if (ret != CL_SUCCESS)
	{
		printf("创建命令队列错误:%d", ret);
		*ptr = 0;
	}
	else
		*ptr = commandQueue;
	return ret;
}

int CommandQueue(cl_context ctx, cl_device_id did)
{
	cl_queue_properties props[] =
	{
		CL_QUEUE_PROPERTIES,
		CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT,
		0
	};
	//CL_QUEUE_PROFILING_ENABLE //若设置，表明对命令进行剖析，否则剖析功能不可用
	return 0;
}

#pragma endregion

#pragma region 计算程序

extern "C" __declspec(dllexport)
uint32_t GetProgramBuildInfo(cl_program * prog, uint64_t did, char* info, size_t length)
{
	cl_device_id device = (cl_device_id)did;
	cl_int status;
	if (info == NULL)
	{
		size_t logSize;
		status = clGetProgramBuildInfo(*prog, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &logSize);
		length = logSize;
	}
	else
	{
		clGetProgramBuildInfo(*prog, device, CL_PROGRAM_BUILD_LOG, length, info, NULL);
	}
	return status;
};

extern "C" __declspec(dllexport)
uint32_t CreateProgramCode(uint64_t did, cl_context * ctx, char* code, cl_program * ptr, char* error)
{
	cl_context context = *ctx;
	cl_device_id device = (cl_device_id)did;
	const char* source = code;// sourceStr.c_str();
	size_t sourceSize[] = { strlen(source) };
	//创建程序对象
	cl_program program = clCreateProgramWithSource(
		context,
		1,
		&source,
		sourceSize,
		NULL);
	//编译程序对象
	cl_int status = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
	if (status != 0)
	{
		size_t logSize;
		clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &logSize);
		char* log;
		log = (char*)malloc(logSize);
		clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, logSize, log, NULL);
		strcpy(error, log);
		printf("clBuild Program failed:%d\n", status);
		printf("clBuild Program failed:%s\n", log);
		return status;
	}
	*ptr = program;
	return 0;
}

extern "C" __declspec(dllexport)
uint32_t CreateProgramFile(uint64_t did, cl_context * ctx, char* file, cl_program * ptr, char* error)
{
	cl_context context = *ctx;
	cl_device_id device = (cl_device_id)did;
	std::string sourceStr;
	cl_uint status = convertToStringEx(file, sourceStr);
	if (status)
	{
		char* str = (char*)"read file error";
		strcpy(error, str);
		return 1;
	}
	const char* source = sourceStr.c_str();
	return CreateProgramCode(did, ctx, (char*)source, ptr, error);
}

#pragma endregion

#pragma region 内核

extern "C" __declspec(dllexport)
int CreateKernal(cl_program * prg, char* name, cl_kernel * ptr)
{
	cl_program program = *prg;
	cl_int ret;
	cl_kernel kernel = clCreateKernel(program, name, &ret);
	*ptr = kernel;
	return ret;
}

extern "C" __declspec(dllexport)
int GetKernalInfo_PECount(cl_kernel * kel, cl_device_id deviceid, int* count)
{
	cl_kernel kernel = *kel;
	size_t len;
	cl_int status = clGetKernelWorkGroupInfo(kernel, deviceid, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, 4, count, &len);
	return status;
}

extern "C" __declspec(dllexport)
int SetKernalParam_Buffer(cl_kernel * kel, int arg_index, cl_mem * buff)
{
	cl_kernel kernel = *kel;
	cl_int status = clSetKernelArg(kernel, arg_index, sizeof(cl_mem), buff);
	if (status != CL_SUCCESS)
	{
		printf("设置内存错误(cl_mem)：%d", status);
	}
	return status;
}

/// <summary>
/// 设置局部内存(局部内存仅工作组可见),不需要返回值
/// </summary>
/// <param name="kel"></param>
/// <param name="arg_index"></param>
/// <param name="size"></param>
/// <returns></returns>
extern "C" __declspec(dllexport)
int SetKernalLocalParam(cl_kernel * kel, int arg_index, size_t size)
{
	cl_kernel kernel = *kel;
	cl_int status = clSetKernelArg(kernel, arg_index, size, NULL);
	if (status != CL_SUCCESS)
	{
		printf("设置局部内存错误(size:%d)：%d", size, status);
	}
	return status;
}

extern "C" __declspec(dllexport)
int SetKernalParam_int(cl_kernel * kel, int arg_index, int value)
{
	cl_kernel kernel = *kel;
	cl_int clnum = 0;
	cl_int status = clSetKernelArg(kernel, arg_index, sizeof(int), &value);
	if (status != CL_SUCCESS)
	{
		printf("设置内存错误(int)：%d", status);
	}
	return status;
}

extern "C" __declspec(dllexport)
int SetKernalParam_uint(cl_kernel * kel, int arg_index, unsigned int value)
{
	cl_kernel kernel = *kel;
	cl_int clnum = 0;
	cl_int status = clSetKernelArg(kernel, arg_index, sizeof(unsigned int), &value);
	if (status != CL_SUCCESS)
	{
		printf("设置内存错误(unsigned int)：%d", status);
	}
	return status;
}

extern "C" __declspec(dllexport)
int SetKernalParam_long(cl_kernel * kel, int arg_index, long value)
{
	cl_kernel kernel = *kel;
	cl_int clnum = 0;
	cl_int status = clSetKernelArg(kernel, arg_index, sizeof(long), &value);
	if (status != CL_SUCCESS)
	{
		printf("设置内存错误(long)：%d", status);
	}
	return status;
}

extern "C" __declspec(dllexport)
int SetKernalParam_ulong(cl_kernel * kel, int arg_index, unsigned long value)
{
	cl_kernel kernel = *kel;
	cl_int clnum = 0;
	cl_int status = clSetKernelArg(kernel, arg_index, sizeof(unsigned long), &value);
	if (status != CL_SUCCESS)
	{
		printf("设置内存错误(unsigned long)：%d", status);
	}
	return status;
}

extern "C" __declspec(dllexport)
int SetKernalParam_float(cl_kernel * kel, int arg_index, float value)
{
	cl_kernel kernel = *kel;
	cl_int clnum = 0;
	cl_int status = clSetKernelArg(kernel, arg_index, sizeof(float), &value);
	if (status != CL_SUCCESS)
	{
		printf("设置内存错误(float)：%d", status);
	}
	return status;
}

extern "C" __declspec(dllexport)
int SetKernalParam_double(cl_kernel * kel, int arg_index, double value)
{
	cl_kernel kernel = *kel;
	cl_int clnum = 0;
	cl_int status = clSetKernelArg(kernel, arg_index, sizeof(double), &value);
	if (status != CL_SUCCESS)
	{
		printf("设置内存错误(double)：%d", status);
	}
	return status;
}

#pragma endregion

#pragma region 数据缓存

//extern "C" __declspec(dllexport)
cl_mem CreateClBuffer_int(cl_context* ctx, void* buff, int size, cl_mem_flags flags, cl_int* pret)
{
	cl_context context = *ctx;
	cl_int ret;
	cl_mem cl_mem = clCreateBuffer(context, flags, sizeof(int) * size, buff, &ret);
	if (ret != CL_SUCCESS)
	{
		printf("Create int Buffer Error:%d", ret);
	}
	*pret = ret;
	return cl_mem;
}

//extern "C" __declspec(dllexport)
cl_mem CreateClBuffer_uint(cl_context* ctx, void* buff, unsigned int size, cl_mem_flags flags, cl_int* pret)
{
	cl_context context = *ctx;
	cl_int ret;
	cl_mem cl_mem = clCreateBuffer(context, flags, sizeof(unsigned int) * size, buff, &ret);
	if (ret != CL_SUCCESS)
	{
		printf("Create unsigned int Buffer Error:%d", ret);
	}
	*pret = ret;
	return cl_mem;
}

//extern "C" __declspec(dllexport)
cl_mem CreateClBuffer_long(cl_context* ctx, void* buff, long size, cl_mem_flags flags, cl_int* pret)
{
	cl_context context = *ctx;
	cl_int ret;
	cl_mem cl_mem = clCreateBuffer(context, flags, sizeof(long) * size, buff, &ret);
	if (ret != CL_SUCCESS)
	{
		printf("Create long Buffer Error:%d", ret);
	}
	*pret = ret;
	return cl_mem;
}

//extern "C" __declspec(dllexport)
cl_mem CreateClBuffer_ulong(cl_context* ctx, void* buff, unsigned long size, cl_mem_flags flags, cl_int* pret)
{
	cl_context context = *ctx;
	cl_int ret;
	cl_mem cl_mem = clCreateBuffer(context, flags, sizeof(unsigned long) * size, buff, &ret);
	if (ret != CL_SUCCESS)
	{
		printf("Create unsigned long Buffer Error:%d", ret);
	}
	*pret = ret;
	return cl_mem;
}

//extern "C" __declspec(dllexport)
cl_mem CreateClBuffer_float(cl_context* ctx, void* buff, int size, cl_mem_flags flags, cl_int* pret)
{
	cl_context context = *ctx;
	cl_int ret;
	cl_mem cl_mem = clCreateBuffer(context, flags, sizeof(float) * size, buff, &ret);
	if (ret != CL_SUCCESS)
	{
		printf("Create float Buffer Error:%d", ret);
	}
	*pret = ret;
	return cl_mem;
}

//extern "C" __declspec(dllexport)
cl_mem CreateClBuffer_double(cl_context* ctx, void* buff, int size, cl_mem_flags flags, cl_int* pret)
{
	cl_context context = *ctx;
	cl_int ret;
	cl_mem cl_mem = clCreateBuffer(context, flags, sizeof(double) * size, buff, &ret);
	if (ret != CL_SUCCESS)
	{
		printf("Create double Buffer Error:%d", ret);
	}
	*pret = ret;
	return cl_mem;
}

extern "C" __declspec(dllexport)
int CreateClBuffer_int(cl_context * ctx, void* buff, int size, cl_mem * ptr, int flag)
{
	cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
	switch (flag)
	{
	case 0x01:
		flags = CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x02:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x03:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	default:
		break;
	}
	cl_int ret;
	cl_mem ptrx = CreateClBuffer_int(ctx, buff, size, flags, &ret);
	*ptr = ptrx;
	return ret;
}

extern "C" __declspec(dllexport)
int CreateClBuffer_uint(cl_context * ctx, void* buff, int size, cl_mem * ptr, int flag)
{
	cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
	switch (flag)
	{
	case 0x01:
		flags = CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x02:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x03:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	default:
		break;
	}
	cl_int ret;
	cl_mem ptrx = CreateClBuffer_uint(ctx, buff, size, flags, &ret);
	*ptr = ptrx;
	return ret;
}

extern "C" __declspec(dllexport)
int CreateClBuffer_long(cl_context * ctx, void* buff, int size, cl_mem * ptr, int flag)
{
	cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
	switch (flag)
	{
	case 0x01:
		flags = CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x02:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x03:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	default:
		break;
	}
	cl_int ret;
	cl_mem ptrx = CreateClBuffer_long(ctx, buff, size, flags, &ret);
	*ptr = ptrx;
	return ret;
}

extern "C" __declspec(dllexport)
int CreateClBuffer_ulong(cl_context * ctx, void* buff, int size, cl_mem * ptr, int flag)
{
	cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
	switch (flag)
	{
	case 0x01:
		flags = CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x02:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x03:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	default:
		break;
	}
	cl_int ret;
	cl_mem ptrx = CreateClBuffer_ulong(ctx, buff, size, flags, &ret);
	*ptr = ptrx;
	return ret;
}

extern "C" __declspec(dllexport)
int CreateClBuffer_float(cl_context * ctx, void* buff, int size, cl_mem * ptr, int flag)
{
	cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
	switch (flag)
	{
	case 0x01:
		flags = CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x02:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x03:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	default:
		break;
	}
	cl_int ret;
	cl_mem ptrx = CreateClBuffer_float(ctx, buff, size, flags, &ret);
	*ptr = ptrx;
	return ret;
}

extern "C" __declspec(dllexport)
int CreateClBuffer_double(cl_context * ctx, void* buff, int size, cl_mem * ptr, int flag)
{
	cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
	switch (flag)
	{
	case 0x01:
		flags = CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x02:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	case 0x03:
		flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR;
		break;
	default:
		break;
	}
	cl_int ret;
	cl_mem ptrx = CreateClBuffer_double(ctx, buff, size, flags, &ret);
	*ptr = ptrx;
	return ret;
}

#pragma endregion

#pragma region 命令队列操作

extern "C" __declspec(dllexport)
int Exec_CommandQueue(cl_command_queue * queue, cl_kernel * kel, uint32_t work_dim, const size_t * global_work_size, cl_event * pevent)
{
	cl_command_queue commandQueue = *queue;
	cl_kernel kernel = *kel;

	cl_event prof_event;
	cl_int status = clEnqueueNDRangeKernel(commandQueue, kernel, work_dim, NULL, global_work_size, NULL, 0, NULL, &prof_event);
	if (status)
	{
		printf("设置命令对象错误：%d\n", status);
	}
	status = clFinish(commandQueue);
	if (status)
	{
		printf("执行结果异常：%d\n", status);
	}
	*pevent = prof_event;
	return status;
}

#pragma endregion

#pragma region 读数据到主机

extern "C" __declspec(dllexport)
int Exec_CommandQueueReadBuffer_int(cl_command_queue * queue, cl_mem * mem, int* ptr, size_t len)
{
	cl_command_queue commandQueue = *queue;
	int* _c;
	_c = (int*)malloc(sizeof(int) * len);
	cl_int status = clEnqueueReadBuffer(commandQueue, *mem, CL_TRUE, 0, sizeof(int) * len, _c, 0, NULL, NULL);
	if (status)
	{
		printf("读取结果异常(int)：%d\n", status);
	}
	memcpy(ptr, _c, sizeof(int) * len);
	free(_c);
	return status;
};

extern "C" __declspec(dllexport)
int Exec_CommandQueueReadBuffer_uint(cl_command_queue * queue, cl_mem * mem, unsigned int* ptr, size_t len)
{
	cl_command_queue commandQueue = *queue;
	unsigned int* _c;
	_c = (unsigned int*)malloc(sizeof(unsigned int) * len);
	cl_int status = clEnqueueReadBuffer(commandQueue, *mem, CL_TRUE, 0, sizeof(unsigned int) * len, _c, 0, NULL, NULL);
	if (status)
	{
		printf("读取结果异常(unsigned int)：%d\n", status);
	}
	memcpy(ptr, _c, sizeof(unsigned int) * len);
	free(_c);
	return status;
};

extern "C" __declspec(dllexport)
int Exec_CommandQueueReadBuffer_long(cl_command_queue * queue, cl_mem * mem, long* ptr, size_t len)
{
	cl_command_queue commandQueue = *queue;
	long* _c;
	_c = (long*)malloc(sizeof(long) * len);
	cl_int status = clEnqueueReadBuffer(commandQueue, *mem, CL_TRUE, 0, sizeof(long) * len, _c, 0, NULL, NULL);
	if (status)
	{
		printf("读取结果异常(long)：%d\n", status);
	}
	memcpy(ptr, _c, sizeof(long) * len);
	free(_c);
	return status;
};

extern "C" __declspec(dllexport)
int Exec_CommandQueueReadBuffer_ulong(cl_command_queue * queue, cl_mem * mem, unsigned long* ptr, size_t len)
{
	cl_command_queue commandQueue = *queue;
	unsigned long* _c;
	_c = (unsigned long*)malloc(sizeof(unsigned long) * len);
	cl_int status = clEnqueueReadBuffer(commandQueue, *mem, CL_TRUE, 0, sizeof(unsigned long) * len, _c, 0, NULL, NULL);
	if (status)
	{
		printf("读取结果异常(unsigned long)：%d\n", status);
	}
	memcpy(ptr, _c, sizeof(long) * len);
	free(_c);
	return status;
};

extern "C" __declspec(dllexport)
int Exec_CommandQueueReadBuffer_float(cl_command_queue * queue, cl_mem * mem, float* ptr, size_t len)
{
	cl_command_queue commandQueue = *queue;
	float* _c;
	_c = (float*)malloc(sizeof(float) * len);
	cl_int status = clEnqueueReadBuffer(commandQueue, *mem, CL_TRUE, 0, sizeof(float) * len, _c, 0, NULL, NULL);
	if (status)
	{
		printf("读取结果异常(float)：%d\n", status);
	}
	memcpy(ptr, _c, sizeof(float) * len);
	free(_c);
	return status;
};

extern "C" __declspec(dllexport)
int Exec_CommandQueueReadBuffer_double(cl_command_queue * queue, cl_mem * mem, double* ptr, size_t len)
{
	cl_command_queue commandQueue = *queue;
	double* _c;
	_c = (double*)malloc(sizeof(double) * len);
	cl_int status = clEnqueueReadBuffer(commandQueue, *mem, CL_TRUE, 0, sizeof(double) * len, _c, 0, NULL, NULL);
	if (status)
	{
		printf("读取结果异常(double)：%d\n", status);
	}
	memcpy(ptr, _c, sizeof(double) * len);
	free(_c);
	return status;
};

#pragma endregion

#pragma region 对象释放

/// <summary>
///
/// type类型
///		0-cl_mem;
///		1-cl_program;
///		2-cl_command_queue;
///		3-cl_context;
///		4-cl_kernel;
/// </summary>
/// <param name="obj"></param>
/// <param name="type"></param>
extern "C" __declspec(dllexport)
void ReleaseClObject(void* obj, int type)
{
	switch (type)
	{
	case 0:
		clReleaseMemObject(*(cl_mem*)(obj));
		break;
	case 1:
		clReleaseProgram(*(cl_program*)(obj));
		break;
	case 2:
		clReleaseCommandQueue(*(cl_command_queue*)(obj));
		break;
	case 3:
		clReleaseContext(*(cl_context*)(obj));
		break;
	case 4:
		clReleaseKernel(*(cl_kernel*)(obj));
		break;
	default:
		break;
	}
}

#pragma endregion